Шаг 2. Провести исследовательский анализ данных (EDA)
Шаг 3. Построить модель прогнозирования оттока пользователей
Шаг 4. Сделать кластеризацию пользователей
Шаг 5. Сформулировать выводы и сделать базовые рекомендации по работе с клиентами
xxxxxxxxxx# План<article id="back"> [Шаг 1. Загрузить данные](#step1)[Шаг 2. Провести исследовательский анализ данных (EDA)](#step2)[Шаг 3. Построить модель прогнозирования оттока пользователей](#step3)[Шаг 4. Сделать кластеризацию пользователей](#step4)[Шаг 5. Сформулировать выводы и сделать базовые рекомендации по работе с клиентами](#step5)xxxxxxxxxximport osc.TemplateExporter.template_path = ['.', os.path.expanduser('~/.jupyter/templates/')]xxxxxxxxxx# Импортирую нужные библиотекиimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsimport plotly.express as pxfrom sklearn.model_selection import train_test_splitfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.linear_model import LogisticRegressionfrom sklearn.metrics import accuracy_score, precision_score, recall_scorefrom sklearn.preprocessing import StandardScalerfrom sklearn.cluster import KMeansfrom scipy.cluster.hierarchy import dendrogram, linkage# Убираем предупреждения об ошибкахimport warningswarnings.simplefilter("ignore")xxxxxxxxxx#Прочитаю и выведу инофрмацию по даннымdata = pd.read_csv('gym_churn.csv')data.info()data.describe(include='all')xxxxxxxxxxПо этим данным можно сделать выводы:- примерно поровну мужчин и женщин- большинство (84,5%) проживаниет или работает в районе, где находится фитнес-центр- почти половина сотрудник компании-партнёра клуба- контактный номер телефона есть почти у всех (90,3%)- 40% клиентов посещает групповые занятия- средний отток составляет 26,5%- возраст варьируется от 18 до 41- средний возраст 29- средняя частота посещений в неделю - меньше двухПо этим данным можно сделать выводы:
xxxxxxxxxx# Приведу колонки к нижнему региструdata.columns = data.columns.str.lower()# Проверю на дубликатыprint('Количество дубликатов в данных:',data.duplicated().sum())# Выведу информациюdisplay(data.head())data.tail()xxxxxxxxxx# Посмотрю на уникальные значения столбцов for column in data.columns: print(column,":") print(data[column].unique())xxxxxxxxxxC данными проблем нет.Нет дулбикатов, нет пропусков, корректный возраст от 18 до 41, нет отрицательных значений. Приступаем к следующему шагу<a href="#back">В начало</a>C данными проблем нет.
Нет дулбикатов, нет пропусков, корректный возраст от 18 до 41, нет отрицательных значений. Приступаем к следующему шагу
xxxxxxxxxx# Шаг 2. Провести исследовательский анализ данных (EDA) <a id="step2"> </a>xxxxxxxxxx# Посмотриm на средние значения признаков в двух группахdata.groupby('churn').mean()xxxxxxxxxxИз усреднённых данных видно, что различия есть в признаках. У тех кто ушел в отток признаки меньше.Из усреднённых данных видно, что различия есть в признаках. У тех кто ушел в отток признаки меньше.
xxxxxxxxxx# Построем гистограммы. Для этого сделаем цикл sns.set()for column in data.columns.drop('churn'): figsize=(8,4) data.groupby('churn')[column].plot(kind = 'hist',legend=True,bins=20) plt.legend(['Остались','Ушли']) plt.xlabel('Распределение признака') plt.ylabel('Количество') plt.title(column) plt.show()xxxxxxxxxxИз графиков видно:- У обоих полов уходят примерно одинаковое количество людей- доля клиентов не проживающих или работающих в районе, где находится фитнес-центр намного меньше.- сотрудников компании-партнёра клуба больше и уходили они реже. - людей которые использовала промо-код от знакомого при оплате первого абонемента меньше и отток у них на много реже(вместе заниматься всегда веселее)- мало клиентов которые не указывали контактный телефон.- чаще всего клиенты уходили когда длительность абонемента была 1 мес.- те кто посещал групповые визиты уходили реже. - пик ухода по возрасту примерно 27 лет. Клиенты возрастом до 25 лет уходят чаще чем остаются. Больше всего клиентов возрастом 30 лет.- средняя частота посещений в неделю за предыдущий месяц больше всего 0, почти не ходят 3 и более раз.Из графиков видно:
xxxxxxxxxx# Построим матрицу корреляцииplt.figure(figsize =(20,10))sns.heatmap(data.corr(),annot=True,vmax = .7,cmap="BuPu",fmt='0.2f')plt.show()xxxxxxxxxxМатрица корреляций подтверждает картину на графиках. Больше всего на отток пользователей влияет:- время с момента первого обращения в фитнес-центр- средняя частота посещений в неделю за предыдущий месяц- возраст- срок до окончания текущего действующего абонемента Проживание или работа в районе, где находится фитнес-центр положительно коррелирует с акцией «приведи друга» . Так же положительно коррелируют если клиент сотрудник компании-партнёра клуба с акцией «приведи друга» или с длительностью текущего действующего абонемента Матрица корреляций подтверждает картину на графиках. Больше всего на отток пользователей влияет:
Проживание или работа в районе, где находится фитнес-центр положительно коррелирует с акцией «приведи друга» . Так же положительно коррелируют если клиент сотрудник компании-партнёра клуба с акцией «приведи друга» или с длительностью текущего действующего абонемента
xxxxxxxxxx# Шаг 3. Построить модель прогнозирования оттока пользователей<a id="step3"> </a>xxxxxxxxxx# Разобьем данные на обучающую и валидационную выборкуX = data.drop('churn',axis = 1)y = data['churn']X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,random_state = 0,stratify = y)xxxxxxxxxxОбучим модель на train-выборке двумя способами.Логистической регрессией и случайным лесом. Для этого сделаю цикл и оцениню метрики accuracy, precision и recall для обеих моделей на валидационной выборкеОбучим модель на train-выборке двумя способами.
Логистической регрессией и случайным лесом. Для этого сделаю цикл и оцениню метрики accuracy, precision и recall для обеих моделей на валидационной выборке
xxxxxxxxxx# Цикл для обучения моделейfor model in [LogisticRegression(random_state=0),RandomForestClassifier(random_state=0)]: model.fit(X_train,y_train) y_pred = model.predict(X_test) print('Accuracy: {:.2f}'.format(accuracy_score(y_test,y_pred))) print('Precision: {:.2f}'.format(precision_score(y_test,y_pred))) print('Recall: {:.2f}'.format(recall_score(y_test,y_pred))) print(" ")xxxxxxxxxxМетрика `Accuracy` Это доля верно угаданных ответов из всех прогнозов`Precision` (Точность) и `Recall` (полнота) чтобы оценить модель без привязки к соотношению классов.precision говорит, какая доля прогнозов относительно "1" класса верна. recall показывает, сколько реальных объектов "1" класса вы смогли обнаружить с помощью модели.Хоть и точность у обоих моделей одинаковая но полнота у логистической регрессии лучше.Логистической регрессией показала себя лучше чем случайный лес.<a href="#back">В начало</a>Метрика Accuracy Это доля верно угаданных ответов из всех прогнозов
Precision (Точность) и Recall (полнота) чтобы оценить модель без привязки к соотношению классов.
precision говорит, какая доля прогнозов относительно "1" класса верна. recall показывает, сколько реальных объектов "1" класса вы смогли обнаружить с помощью модели.
Хоть и точность у обоих моделей одинаковая но полнота у логистической регрессии лучше.
Логистической регрессией показала себя лучше чем случайный лес.
xxxxxxxxxx# Шаг 4. Сделать кластеризацию пользователей<a id="step4"> </a>xxxxxxxxxx# Для начала стандартизируем данные.scaler = StandardScaler()# Обучаем и стандартизируем данныеX_st = scaler.fit_transform(X)X_st # Выведу на экранxxxxxxxxxx# Сделаю матрицу расстоянийlinked = linkage(X_st, method = 'ward') # В переменной linked сохранена таблица «связок» между объектами.# Нарисуем дендрограмму. plt.figure(figsize=(15, 10)) # Внимание: отрисовка дендрограммы может занять время!dendrogram(linked, orientation='top')plt.show()xxxxxxxxxxНа основании полученного, можно выделить 4 кластера клиентов. Для более детального рассмотрения можно выделить 6 кластеров клиента(т.к. фиолетовый можно разделить на 3 больших кластера)На основании полученного, можно выделить 4 кластера клиентов. Для более детального рассмотрения можно выделить 6 кластеров клиента(т.к. фиолетовый можно разделить на 3 больших кластера)
xxxxxxxxxx# Обучиm модель кластеризации. За число кластеров возьмём n = 5# задаём модель k_means с числом кластеров 5km = KMeans(n_clusters = 5, random_state = 0)# прогнозируем кластеры для наблюдений (алгоритм присваивает им номера от 0 до 4)labels = km.fit_predict(X_st)# сохраняем метки кластера в поле нашего датасетаdata['cluster'] = labels# Выведу на экранdata.head()xxxxxxxxxx# выводим статистику по средним значениям наших признаков по кластеруdata.groupby('cluster').mean()xxxxxxxxxxКластеры почти не отличаются по среднему возрасту и полу.`Кластер 0`:- клиенты с самой большой длительностью контракта- с высокой вероятностью пользующиеся партнерской программой или приглашениями друзей- большие траты на дополнительные услуги фитнес-центра- cамая большая вероятность посещения групповых занятий- живут или работают возле фитнес-центра- самый большой срок до окончания текущего действующего абонемента (в месяцах)- отток 2%- средняя частота посещений в неделю за предыдущий месяц 2 раза`Кластер 1`:- меньший срок контракта и меньшее количество посещений групповых занятий, чем в кластере 0- для них характерна меньшая частота посещений (менее 2), которая падает за последний месяц;- нет наличия контактного телефона- отток 26% `Кластеры 2 и 3`:- клиенты с самой большой вероятностью оттока- самая низкая продолжительность контракта;- самое низкое среднее количество посещений групповых занятий- самая значительная разница между посещением в среднем и посещением за последний месяц - второе значительно ниже- для кластера 3 характерен самый низкий среди всех кластеров средний возраст- показатели акции «приведи друга» для кластера 2 самые низкие в датасете;- в кластер 2 попали только те, кто не живет/работает возле фитнес-центра.`Кластер 4`:- самые большие траты на дополнительные услуги фитнес-центра- самая высокая посещаемость, которая не падает за последний месяц- самый высокий среди всех кластеров средний возраст- большая вероятность посещения групповых занятийКластеры почти не отличаются по среднему возрасту и полу.
Кластер 0:
Кластер 1:
Кластеры 2 и 3:
Кластер 4:
xxxxxxxxxxdata.head(10).T # Переверну xxxxxxxxxx# Сделаю распределение признаков для кластеровfor column in data.columns.drop(['cluster','churn','avg_class_frequency_current_month','avg_class_frequency_total','avg_additional_charges_total','age']): sns.catplot(x="cluster", y=column, hue="churn", data=data, kind="bar", ci=None,legend=False) plt.title(column) plt.ylabel(" ") plt.legend(['Остались','Ушли'],framealpha=.2,loc='best') plt.show()xxxxxxxxxx# Сделаю распределение признаков для кластеровfor_box = ['avg_class_frequency_current_month','avg_class_frequency_total','avg_additional_charges_total','age']for column in for_box: fig = px.box(data,x='cluster', y=column,color='churn',title=column) fig.show()xxxxxxxxxxСредняя частота посещений в неделю за все время с начала действия абонемента у 3 кластера в оттоке выше чем у тех кто остался. В остальном у тех кто остались показатели выше. только в 2-х кластерах есть 18 летние и они в оттоке. Средний возраст 30 лет, как и писал выше.Средняя частота посещений в неделю за все время с начала действия абонемента у 3 кластера в оттоке выше чем у тех кто остался. В остальном у тех кто остались показатели выше. только в 2-х кластерах есть 18 летние и они в оттоке. Средний возраст 30 лет, как и писал выше.
xxxxxxxxxx# Посчитаем долю оттока# Посчитаем общее количество клиентовshare = data.groupby('cluster').agg(total=('gender','count')).reset_index() # Посчитаем количество клиентов которые ушлиshare['churn'] = data.groupby('cluster')['churn'].sum()# Посчитаем долю оттокаshare['percent_churn'] = round((share['churn'] / share['total'])* 100,2)share # Выведем на экранxxxxxxxxxxСамые надежные кластеры это `0` и `4` . У `0` ушло `2.77%` а у `4` `6.81%`. Склонные к оттоку кластеры это `2(44.36%)` и `3(51.43%)`<a href="#back">В начало</a>Самые надежные кластеры это 0 и 4 . У 0 ушло 2.77% а у 4 6.81%. Склонные к оттоку кластеры это 2(44.36%) и 3(51.43%)
xxxxxxxxxx# Шаг 5. Сформулировать выводы и сделать базовые рекомендации по работе с клиентами<a id="step5"> </a>xxxxxxxxxx### Качество данныхХорошо бы иметь больше данных для построения более качественной модели клиента. Т.к не известно за какой период собраны эти данные, может они уже не актуальны. В какой валюте тратят клиенты деньги, на что именно. По этим параметрам можно составить и доработать модель клиента. Какие групповые занятия посещают и т.к### Общие характеристики клиентов, которые склонны к оттокуСамые важные причины, влияющие на отток пользователей, следующие:- меньший возраст- отсутствие проживания или работы в районе, где находится фитнес-центр- маленькая продолжительность контракта,- низкий уровень партнерских программ и акции "приведи друга" - низкий факт посещения групповых занятий### РекомендацииДля группы пользователей кластера `0` и `4` лучше ничего не делать, пока показатели не изменяться. Зачем влезать туда что и так хорошо работает`1` кластеру можно предложить новые групповые занятия или скидку,бесплатную услугу от фитнес-центра: кафе, спорт-товары, косметический и массажный салон т.к их показатели высоки и им чего-то не хватает. Здесь надо провести более детальный анализ.Но этим людям не надо быть навязчивыми это может их отпугнуть т.к они не оставляли свой номер телефона. Это может говорить о том что лишний спам им не нужен.`2` кластер. Это люди которые не проживанию или работают в районе, где находится фитнес-центр. Так же у них низкий показатель акции «приведи друга» и факт посещения групповых занятий. Возможно, им скучно заниматься одним или они находят фитнес-центр поближе к дому или работе. Можно попробовать предложить им побольше групповых занятий, там они могут познакомиться с людьми и вместе ходить в зал и тогда расстояние покажется незначительной проблемой.`3` кластер. Это самая большая группа людей и так же они самая молодая группа. Они посещают реже всех фитнес-центр, может дело в работе, нехватает мотивации или дело в сезоне. Ведь неизвестно когда они уходили. Им можно предложить скидку на абонемент для дополнительной мотивации или сделать упор на другие услуги фитнес-центра, вроде массажа, сауны, бассейна чтобы они могли расслабиться после работы. Хорошо бы иметь больше данных для построения более качественной модели клиента. Т.к не известно за какой период собраны эти данные, может они уже не актуальны. В какой валюте тратят клиенты деньги, на что именно. По этим параметрам можно составить и доработать модель клиента. Какие групповые занятия посещают и т.к
Самые важные причины, влияющие на отток пользователей, следующие:
Для группы пользователей кластера 0 и 4 лучше ничего не делать, пока показатели не изменяться. Зачем влезать туда что и так хорошо работает
1 кластеру можно предложить новые групповые занятия или скидку,бесплатную услугу от фитнес-центра: кафе, спорт-товары, косметический и массажный салон т.к их показатели высоки и им чего-то не хватает. Здесь надо провести более детальный анализ.
Но этим людям не надо быть навязчивыми это может их отпугнуть т.к они не оставляли свой номер телефона. Это может говорить о том что лишний спам им не нужен.
2 кластер. Это люди которые не проживанию или работают в районе, где находится фитнес-центр. Так же у них низкий показатель акции «приведи друга» и факт посещения групповых занятий. Возможно, им скучно заниматься одним или они находят фитнес-центр поближе к дому или работе. Можно попробовать предложить им побольше групповых занятий, там они могут познакомиться с людьми и вместе ходить в зал и тогда расстояние покажется незначительной проблемой.
3 кластер. Это самая большая группа людей и так же они самая молодая группа. Они посещают реже всех фитнес-центр, может дело в работе, нехватает мотивации или дело в сезоне. Ведь неизвестно когда они уходили. Им можно предложить скидку на абонемент для дополнительной мотивации или сделать упор на другие услуги фитнес-центра, вроде массажа, сауны, бассейна чтобы они могли расслабиться после работы.